﻿using System;
using System.Data;
using System.Data.Common;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Kugar.Core.BaseStruct;
using Kugar.Core.ExtMethod;
using SqlSugar;

#if NETFULL
    using DataTable = System.Data.DataTable;
#endif

#if NETCOREAPP
    using DataTable = SqlSugar.DataTable;
#endif

namespace Kugar.Tools.SQLHelper
{
    public interface IDbHelperContext:IDisposable
    {
        DataTable ExecuteTableBySQL(string sqlText, params DbParameter[] parameters);

        int ExecuteNoQueryBySQL(string sqlText, params DbParameter[] parameters);

        DbConnection Connection { get; }

        DbTransaction BeginTransaction();

        SqlSugarClient DbClient { get; }
    }

    public interface ITable<T> where T : class, new()
    {
        #region Query 相关函数

        T[] QuerySql(string whereStr);

        T[] QuerySql(string fields, string whereStr);

        ISugarQueryable<T> Query();

        VM_PagedList<T> QueryWithPaged(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize);

        Task<VM_PagedList<T>> QueryWithPagedAsync(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize);

        VM_PagedList<TResult> QueryWithPaged<TResult>(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize);

        Task<VM_PagedList<TResult>> QueryWithPagedAsync<TResult>(Expression<Func<T, bool>> whereExp, int pageIndex,
            int pageSize);

        #endregion

        #region Delete 相关函数

        int Delete(string whereStr);

        Task<int> DeleteAsync(string whereStr);

        int Delete(Expression<Func<T, bool>> whereExp);

        Task<int> DeleteAsync(Expression<Func<T, bool>> whereExp);        

        #endregion


        #region Insert

        int Insert(T entity);

        Task<int> InsertAsync(T entity);

        int Insert(params T[] entities);

        Task<int> InsertAsync(params T[] entities);

        #endregion


        IUpdateable<T> Update(Expression<Func<T, bool>> whereExp);

        string TableName { get; }

        IDbHelperContext DbContext { get; }
        
    }

    public abstract class TableBase<T> : ITable<T> where T:class,new()
    {
        private AsyncLocal<>

        public TableBase(IDbHelperContext dbContext)
        {
            DbContext = dbContext;
        }

        #region Query 相关函数

        public virtual T[] QuerySql(string whereStr)
        {
            return Client.Queryable<T>().Where(whereStr).ToList().ToArrayEx();
        }

        public virtual async Task<T[]> QuerySqlAsync(string whereStr)
        {
            return Client.Queryable<T>().Where(whereStr).ToList().ToArrayEx();
        }

        public virtual T[] QuerySql(string fields, string whereStr)
        {
            return Client.Queryable<T>().Where(whereStr).Select(fields).ToList().ToArrayEx();
        }

        public virtual async Task<T[]> QuerySqlAsync(string fields, string whereStr)
        {
            return (await Client.Queryable<T>().Where(whereStr).Select(fields).ToListAsync()).ToArrayEx();
        }

        public virtual ISugarQueryable<T> Query()
        {
            return Client.Queryable<T>();
        }

        public virtual VM_PagedList<T> QueryWithPaged(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize)
        {
            int count = 0;

            var lst = Query().Where(whereExp).ToPageList(pageIndex, pageSize, ref count);

            var result = new VM_PagedList<T>(lst, pageIndex, pageSize, count);

            return result;
        }

        public virtual async Task<VM_PagedList<T>> QueryWithPagedAsync(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize)
        {
            //int count=0;

            var lst = await Query().Where(whereExp).ToPageListAsync(pageIndex, pageSize, 0);

            var result = new VM_PagedList<T>(lst.Key, pageIndex, pageSize, lst.Value);

            return result;
        }

        public virtual VM_PagedList<TResult> QueryWithPaged<TResult>(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize)
        {
            int count = 0;

            var lst = Query().Where(whereExp).Select<TResult>().ToPageList(pageIndex, pageSize, ref count);

            var result = new VM_PagedList<TResult>(lst, pageIndex, pageSize, count);

            return result;
        }

        public virtual async Task<VM_PagedList<TResult>> QueryWithPagedAsync<TResult>(Expression<Func<T, bool>> whereExp, int pageIndex, int pageSize)
        {
            //int count=0;

            var lst = await Query().Where(whereExp).Select<TResult>().ToPageListAsync(pageIndex, pageSize, 0);

            var result = new VM_PagedList<TResult>(lst.Key, pageIndex, pageSize, lst.Value);

            return result;
        }

        #endregion

        #region Delete 相关函数

        public virtual int Delete(string whereStr)
        {
            return Client.Deleteable<DataTable>().Where(whereStr).ExecuteCommand();
        }

        public virtual async Task<int> DeleteAsync(string whereStr)
        {
            return await Client.Deleteable<DataTable>().Where(whereStr).ExecuteCommandAsync();
        }

        public virtual int Delete(Expression<Func<T, bool>> whereExp)
        {
            return Client.Deleteable<T>(whereExp).ExecuteCommand();
        }

        public virtual async Task<int> DeleteAsync(Expression<Func<T, bool>> whereExp)
        {
            return await Client.Deleteable<T>(whereExp).ExecuteCommandAsync();
        }

        #endregion

        #region Insert 相关函数

        public virtual int Insert(T entity)
        {
            return Client.Insertable<DataTable>(entity).ExecuteCommand();
        }

        public virtual async Task<int> InsertAsync(T entity)
        {
            return Client.Insertable<DataTable>(entity).ExecuteCommand();
        }

        public virtual int Insert(params T[] entities)
        {
            return Client.Insertable<DataTable>(entities).ExecuteCommand();
        }

        public virtual async Task<int> InsertAsync(params T[] entities)
        {
            return Client.Insertable<DataTable>(entities).ExecuteCommand();
        }



        #endregion

        /// <summary>
        /// 更新表,返回一个UpdaterBudler
        /// </summary>
        /// <param name="whereExp"></param>
        /// <returns></returns>
        public IUpdateable<T> Update(Expression<Func<T, bool>> whereExp)
        {
            return Client.Updateable<T>().Where(whereExp);
        }

        public abstract string TableName { get; }

        protected virtual SqlSugarClient Client => DbContext.DbClient;

        public virtual IDbHelperContext DbContext { get; }

    }

}
